home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / amiga / bmake15.lzh / make.c < prev    next >
C/C++ Source or Header  |  1991-11-10  |  6KB  |  229 lines

  1. /*    make.c
  2.  *    (c) Copyright 1991 by Ben Eng, All Rights Reserved
  3.  *
  4.  */
  5.  
  6. #include <string.h>
  7. #include <ctype.h>
  8. #include <fcntl.h>
  9.  
  10. #include <clib/exec_protos.h>
  11. #include <clib/dos_protos.h>
  12.  
  13. #include "make.h"
  14. #include "depend.h"
  15.  
  16. static int make_implicit( char *goalname, int *remake_flag );
  17.  
  18. /*
  19.  *        Get the modification time of a file.  If the file
  20.  *        doesn't exist, it's modtime is set to 0.
  21.  */
  22.  
  23. static time_t
  24. modtime( char *filename )
  25. {
  26.     struct FileInfoBlock *fib;
  27.     BPTR myLock;
  28.     long ioErr;
  29.     time_t mtime = 0L;
  30.  
  31.     fib = (struct FileInfoBlock *)malloc( sizeof(struct FileInfoBlock));
  32.     if( fib ) {
  33.         if( !(myLock = Lock( filename, ACCESS_READ ))) {
  34.             if( (ioErr = IoErr()) != ERROR_OBJECT_NOT_FOUND)
  35.                 logprintf( "Can't Lock '%s'; error %ld\n", filename, ioErr );
  36.         }
  37.         else if( !Examine( myLock, fib )) {
  38.             UnLock(myLock);
  39.             logprintf( "Can't Examine '%s'; error %ld", filename, IoErr() );
  40.         }
  41.         else {
  42.             mtime = fib->fib_Date.ds_Tick / TICKS_PER_SECOND +
  43.                  60*fib->fib_Date.ds_Minute + 86400 * fib->fib_Date.ds_Days;
  44.             UnLock( myLock );
  45.         }
  46.         free( fib );
  47.     }
  48.     return( mtime );
  49. }
  50.  
  51. /* return true if targ1 is newer than targ2 OR if either is missing */
  52. int
  53. isnewer( char *targ1, char *targ2 )
  54. {
  55.     time_t t1, t2;
  56.     long diff;
  57.     int retval;
  58.  
  59.     t1 = modtime( targ1 );
  60.     t2 = modtime( targ2 );
  61.     if( !t1 || !t2 )
  62.         retval = 1;
  63.     else {
  64.         diff = (long)(t1 - t2);
  65.         retval = (diff > 0L) ? 1 : 0;
  66.     }
  67.  
  68.     debugprintf( 5, ("isnewer %s=%ld,%s=%ld diff=%ld: %s\n", targ1, t1,
  69.         targ2, t2, diff, (retval) ? "yes" : "no" ));
  70.  
  71.     return( retval );
  72. }
  73.  
  74. /* recursively make a target filename */
  75. int
  76. make_filename( const char *goalname, int *made )
  77. {
  78.     int remake_flag = (Param.all_mode) ? 1 : 0;    
  79.     struct depend *dep;
  80.     struct List *cmdlist = NULL;
  81.     struct target *goal = find_target( goalname );
  82.     char *depname = NULL;
  83.  
  84.     Global.recursion_level++;
  85.     *made = (Param.all_mode) ? 1 : 0;
  86.  
  87.     if( Global.recursion_level == 1 ) {
  88.         logprintf( "\tmake( %s )\n", goalname );
  89.     }
  90.     else  {
  91.         debugprintf( 1, ( "\n\tmake %d ( %s )\n", Global.recursion_level,
  92.         goalname ));
  93.     }
  94.     if( goal ) {
  95.         if( (goal->flags & TF_NEVER) ||
  96.             ((goal->flags & (TF_ONCE | TF_MADE)) == (TF_ONCE | TF_MADE)) ) {
  97.             logprintf( "\tskipping %s\n", goalname );
  98.             return( 0 );
  99.         }
  100.         if( goal->dependlist.lh_Head->ln_Succ ) {
  101.             for( dep = (struct depend *)goal->dependlist.lh_Head; 
  102.                 dep->node.ln_Succ; dep = dep->node.ln_Succ ) {
  103.                 int made_flag = 0;
  104.  
  105.                 debugprintf( 1, ("%s depends on %s\n", goalname, dep->name ));
  106.                 if( make_filename( dep->name, &made_flag ))
  107.                     return( 1 );
  108.                 if( made_flag || (!(goal->flags & TF_PHONY) &&
  109.                     isnewer( dep->name, goalname ))) {
  110.                     depname = dep->name;
  111.                     remake_flag = 1;
  112.                     debugprintf( 4, ("%s was made\n", dep->name ));
  113.                 }
  114.             } /* for */
  115.         } 
  116.         else
  117.             remake_flag = 1; /* has no dependencies */
  118.         cmdlist = (goal->flags & TF_OWNER ) ? &goal->commandlist :
  119.             goal->alternate;
  120.     } /* if */
  121.  
  122.     /* if no explicit rule for goal OR goal has no commands */
  123.     if( !goal || (!cmdlist->lh_Head->ln_Succ && !(goal->flags & TF_PHONY))) {
  124.         int retval = make_implicit( goalname, &remake_flag );
  125.         --Global.recursion_level;
  126.         if( retval == -1 ) {
  127.             if( !goal )
  128.                 logprintf( "don't know how to make %s\n", goalname );
  129.             else
  130.                 retval = 0;
  131.         }
  132.         *made = remake_flag;
  133.         return( retval );
  134.     }
  135.     else {
  136.         --Global.recursion_level;
  137.         if( (remake_flag || (goal->flags & TF_ALWAYS))
  138.             && cmdlist->lh_Head->ln_Succ ) {
  139.             int retval;
  140.  
  141.             set_target_macros( goalname, depname );
  142.             retval = recipe( goalname, cmdlist );
  143.             set_target_macros( NULL, NULL );
  144.             if( retval )
  145.                 return( 1 );
  146.             goal->flags |= TF_MADE;
  147.         }
  148.         else if( !remake_flag ) {
  149.             debugprintf( 2,("%s is up to date\n", goal->name ));
  150.         }
  151.     }
  152.     if( !(goal->flags & TF_INVIS) )
  153.         *made = remake_flag;
  154.     debugprintf( 4, ("%s remake_flag = %d\n", goalname, remake_flag ));
  155.     return( 0 );
  156. }
  157.  
  158. /*    use this inference engine as a last resort
  159.  *    use pattern rules to determine dependencies and commands for goalname
  160.  */
  161. static int
  162. make_implicit( char *goalname, int *remake_flag )
  163. {
  164.     char *depfile = (char *)malloc( MAXPATHNAME );
  165.     struct patternrule *pr;
  166.     struct List *cmdlist;
  167.     struct target *goal;
  168.     int makeit_flag = (Param.all_mode) ? 1 : *remake_flag;
  169.  
  170.     debugprintf( 1, ("\tmake_implicit( %s,%d)\n", goalname, *remake_flag ));
  171.                 
  172.     if( !depfile )
  173.         goto death; /* no mem */
  174.  
  175.     *depfile = (char)0;
  176.     for( pr = &Global.patternlist.lh_Head; pr->node.ln_Succ;
  177.         pr = pr->node.ln_Succ ) {
  178.         if( pattern_match( pr->tar_pat, goalname )) {
  179.             debugprintf( 2, ("Matched Pattern rule %s: %s to %s\n",
  180.                 pr->tar_pat, pr->dep_pat, goalname ));
  181.             if( *pr->dep_pat ) {
  182.                 map_to_pattern( depfile, pr->tar_pat, pr->dep_pat, goalname );
  183.                 if( !access( depfile, 0 )) { /* found it */
  184.                     int made_flag;
  185.  
  186.                     debugprintf( 2, ("double pattern rule matches %s\n",
  187.                         depfile ));
  188.                     if( make_filename( depfile, &made_flag ))
  189.                         goto death;
  190.                     if( made_flag || isnewer( depfile, goalname ))
  191.                         makeit_flag = 1;
  192.                     break; /* found it */
  193.                 } /* else not the right rule, continue to find another */
  194.             }
  195.             else {
  196.                 debugprintf( 2, ("single suffix rule applies\n" ));
  197.                 makeit_flag = 1;
  198.                 break; /* found it */
  199.             }
  200.         } /* if */
  201.     } /* for each suffix rule */
  202.  
  203.     goal = ( pr->node.ln_Succ ) ? pr->targ : default_target;
  204.     if( !goal ) {
  205.         free( depfile );
  206.         debugprintf( 4, ("returning -1, remake_flag = %d\n", *remake_flag ));
  207.         return( -1 );
  208.     }
  209.     if( makeit_flag ) {
  210.         cmdlist = (goal->flags & TF_OWNER ) ?
  211.             &goal->commandlist : goal->alternate;
  212.         if( cmdlist && cmdlist->lh_Head->ln_Succ ) {
  213.             set_target_macros( goalname, depfile );
  214.             if( recipe( goalname, cmdlist ))
  215.                 goto death;
  216.             set_target_macros( NULL, NULL );
  217.             if( !(goal->flags & TF_INVIS) )
  218.                 *remake_flag = 1;
  219.         }
  220.     }
  221.     free( depfile );
  222.     debugprintf( 4, ("implicit %s remake_flag = %d\n", goalname, *remake_flag ));
  223.     return( 0 );
  224. death:
  225.     if( depfile )
  226.         free( depfile );
  227.     return( 1 );
  228. }
  229.